/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                           *
 *                          Copyright (c) 2010                               *
 *                  Alen Stojanov [ ioi.alen@gmail.com ]                     *
 *                Jacobs University Bremen, Bremen, Germany                  *
 *                                                                           *
 *                          All Rights Reserved.                             *
 *                                                                           *
 *    Permission to use, copy, modify and distribute this software and       *
 *    its documentation is hereby granted, provided that both the            *
 *    copyright notice and this permission notice appear in all copies of    *
 *    the software, derivative works or modified versions, and any           *
 *    portions thereof, and that both notices appear in supporting           *
 *    documentation.                                                         *
 *                                                                           *
 *    This code is distributed in the hope that it will be useful, but       *
 *    WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS       *
 *    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER          *
 *    RESULTING FROM THE USE OF THIS SOFTWARE.                               *
 *                                                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef TSDATA_H_
#define TSDATA_H_

#include <QFile>
#include <QVector>
#include <QMap>
#include <QColor>

#include "tsthread.h"

/**
 * @class TSData
 * @author Alen Stojanov, September 2010
 *
 * @brief Represent Time Series Data as a single object
 *
 * This class represents Time Series Data. TODO: Write explanation
 */
class TSData : QObject
{
	Q_OBJECT

public:
	/**
	 * @brief Define the type of the TSData
	 *
	 * We distinguish two types of time series, the first one is
	 * a SingleColumn. In this TSData, the "time" component will
	 * be populated with values from 0 to the size of the TSData
	 */
	enum TSDataType {
		SingleColumn,
		DoubleColumn
	};
	/**
	 * @brief Determine the type of nearest point searched
	 */
	enum NearestType {
		NearestRound,
		NearestFloor,
		NearestCeil
	};

	enum BinningType {
		Average,
		Highest
	};

	/**
	 * @brief Default constructor
	 *
	 * Create an instance of TSData such that name of the data will be specified,
	 * type of the data and the color used for this particular data in the views
	 *
	 * @param name 	The name of the time series
	 * @param type	The type of the time series (Single or Double column)
	 * @param color The color of the data being read
	 */
	TSData(QString name, enum TSDataType type, QColor color);
	/**
	 * @brief Read a file and populate the TSData
	 *
	 * This method populates the vectors of TSData by reading the file given as
	 * argument.
	 *
	 * @param file		The file where the input time series will be imported
	 * @param thread	The thread which calls read data method, used for feedback
	 */
	bool readData(QFile &file, TSThread* thread = NULL);
	/**
	 * @brief Read the specified content and populate the TSData
	 *
	 * This method populates the vectors of TSData by specifying the
	 * content given as argument
	 *
	 * @param fileContent 	The content of the file passed as a string
	 * @param thread	The thread which calls read data method, used for feedback
	 */
	bool readData(QString &fileContent, TSThread* thread = NULL);
	/**
	 * @brief 			Return the size of the TSData
	 * @return 			The size of the y vector
	 */
	int size();
	/**
	 * @brief 			Get the type of the data
	 * @return 			Type of the Time Series
	 */
	enum TSDataType getType ();
	/**
	 * @brief 			Get the "time" component at particular X value
	 * @param x 		value of the "time" component
	 * @return 			"time" component
	 */
	double getX(int x);
	/**
	 * @brief 			Get the "value" component at particular Y value
	 * @param y 		The position of the "value" component
	 * @return 			"value" component
	 */
	double getY(int y);
	/**
	 * @brief 			Return the index which is nearest to the x-axis coordinate for the given value
	 * @param value		The value of the x-axis
	 * @param type		The type of the Nearest search
	 * @return			The index of the nearest value
	 */
	int getNearestXIndex(double value, TSData::NearestType type) const;
	/**
	 * @brief			Calculate the distance of two TSData sets
	 * @return			Return Euclidian distance
	 */
	double distance (TSData* data);
	/**
	 * @brief			Calculate the distance of two TSData sets
	 * @return			Return Euclidian distance
	 */
	double distance (TSData& data);

private:
	/**
	 * @brief 	The name and ID of the TSData
	 */
	QString name;
	/**
	 * @brief 	Type of the TSData (Single or Double Column)
	 */
	enum TSDataType type;
	/**
	 * @brief The color of the data when rendered in TSView
	 */
	QColor color;
	/**
	 * @brief 	Represent time data (the x coordinates)
	 */
	QVector<double> x;
	/**
	 * @brief 	Represent value data (the y coordinates)
	 */
	QVector<double> y;
	/**
	 * @brief 	The maximum X value
	 */
	double maxX;
	/**
	 * @brief 	The minimum X value
	 */
	double minX;
	/**
	 * @brief 	The maximum Y value
	 */
	double maxY;
	/**
	 * @brief 	The minimum Y value
	 */
	double minY;
	/**
	 * @brief 	Size of the TSData
	 */
	int dataSize;
	/**
	 * @brief 	Process a single line of the time series input
	 * @param 	line Single input line
	 */
	void processLine(QString line);
	/**
	 * @brief 	Return the index which is nearest to the x-axis coordinate for the given value
	 * 		  	by performing a binary search
	 *
	 * @param value		The value of the x-axis
	 * @param type		The type of the Nearest search
	 * @param start		The starting index
	 * @param end		The ending index
	 * @return			The index of the nearest value
	 */
	int getNearestXIndexBin(double value, TSData::NearestType type, int start, int end) const;
	/**
	 * @brief Calculate minX, minY, maxX, maxX
	 */
	void calculateExtremes();
	/**
	 * In case a distance has been calculated, map the value
	 */
	QMap<TSData*, double> distanceMap;

public:

	/**
	 * Convert the data to a binned version with less entries
	 */
	TSData* toBinned(long binSize, BinningType type);

	/**
	 * @brief 	Get maximum X value of the data
	 */
	double getMaxX() const;
	/**
	 * @brief 	Get minimum X value of the data
	 */
	double getMinX() const;

	/**
	 * @brief 	Get maximum Y value of the data
	 */
	double getMaxY() const;
	/**
	 * @brief 	Get maximum Y value of the data in a particular range
	 */
	double getMaxY(double rangeMinX, double rangeMaxX);

	/**
	 * @brief 	Get minimum Y value of the data
	 */
	double getMinY() const;
	/**
	 * @brief 	Get minimum Y value of the data in a given range
	 */
	double getMinY(double rangeMinX, double rangeMaxX);

	/**
	 * @brief 	Get the color of the data object
	 */
	QColor 	getColor();
	/**
	 * @brief 	Return the color of the object
	 */
	void 	setColor(QColor color);
	/**
	 * @brief	Get the name of the data
	 */
	QString getName();
	/**
	 * Default destructor
	 */
	virtual ~TSData();
};

#endif /* TSDATA_H_ */
